<?php
/**
 * Created by Administrator
 * User: longli
 * VX: isa1589518286
 * Date: 2020/08/12
 * Time: 10:50
 * @link http://www.lmterp.cn
 */

namespace app\common\service\platform;

use app\common\library\Tools;
use app\common\model\Account;
use app\common\model\AccountSyncLog;
use app\common\model\SysCountries;
use app\common\model\OrdersTemp;
use app\common\service\orders\OrderService;
use Exception;
use LazopClient;
use LazopRequest;
use think\facade\Log;

require_once \Env::get("root_path") . 'extend/lazada/LazopSdk.php';
/**
 * lazada 服务接口，平台需要提供回调地址，需要自己注册开发者账号
 * Class LazadaService
 * @package app\common\service\lazada
 * @link https://open.lazada.com/doc/api.htm?spm=a2o9m.11193487.0.0.3ac413feHAnzbS#/api?cid=8&path=/orders/get
 */
class LazadaService extends BasePlatformService
{
    public static $tokenField = [
        'required' => [ // 必填字段
            [
                'type' => 'text',
                'name' => 'appkey',
                'field' => 'appkey',
            ],
            [
                'type' => 'text',
                'name' => 'app_secret',
                'field' => 'app_secret',
            ],
            [
                'type' => 'text',
                'name' => 'refresh_token',
                'field' => 'refresh_token',
            ],
        ],
        'option' => [ // 可选字段
            [
                'type' => 'text',
                'name' => 'access_token',
                'field' => 'access_token',
                'readonly' => true,
            ],
        ],
    ];

    protected $apiUrls = [];

    /**
     * @var LazopClient
     */
    protected $client;

    /**
     * @var LazopRequest
     */
    protected $request;

    public function init()
    {
        $this->apiUrls = array_filter(Tools::trim(explode(',', $this->getBaseUrl())));
    }

    /**
     * @inheritDoc
     */
    public function syncOrder(OrdersTemp $ordersTemp)
    {
        $data = $ordersTemp->order_info;
        $info = [];
        $invoiceNumber = [];
        $trackingCode = "";
        if(!isset($data['order_detail'])) return false;
        foreach($data['order_detail'] as $item)
        {
            $trackingCode = $item['tracking_code'];
            $invoiceNumber[] = $item['invoice_number'];
            $info[] = [
                //"qty"           => 1, // 数量
                "return_qty"    => 0, // 取消数量
                "price"         => $item['item_price'], // 售价
                "platform_sku"  => $item['sku'], // sku
                "name"          => $item['name'], // 产品名称
                "image_url"         => $item['product_main_image'], // 图片地址
                'url'           => $item['product_detail_url'], // 商品在线地址
            ];
        }
        $platform = $this->getAccountById($ordersTemp->account_id)->platform;

        $address = $data['address_shipping'];
        $countryObj = SysCountries::get(["name_en" => $address['country']]);
        $order = [
            "order_no"                  => $ordersTemp->order_no,
            "account_id"                => $ordersTemp->account_id,
            "platform_name"             => $platform->name, // 平台名称
            "order_platform_status"     => is_array($data["statuses"]) ? join(',', $data["statuses"]) : $data["statuses"], // 订单在平台的状态
            "buyer_first_name"          => $address['first_name'], // 客户名称
            "buyer_last_name"           => $address['last_name'], // 客户名称
            "buyer_phone"               => $address["phone"], // 电话
            "buyer_mobile"              => $address["phone2"], // 电话
            "country"                   => $address['country'], // 国家
            "buyer_country_code"        => $countryObj->code_two, // 国家编码
            "buyer_city"                => $address['city'], // 城市
            "buyer_post_code"           => $address['post_code'], // 邮编
            "buyer_address_1"           => $address['address1'], // 买家收货地址1
            "buyer_address_2"           => $address['address2'], // 买家收货地址2
            "buyer_address_3"           => $address['address3'], // 买家收货地址3
            "shipping_price"            => $data['shipping_fee'], // 订单运费
            "order_source_create_time"  => $this->parseTimeToDate($data['created_at']), // 订单在平台生成的时间
            "latest_delivery_time"      => null, // 最迟发货时间
            "payment_method"            => $data['payment_method'], // 付款方式
            "order_price"               => $data['price'], // 订单金额
            "total_price"               => $data['price'] + $data['shipping_fee'], // 订单总金额
            "order_pay_time"            => null, // 订单支付时间
            "currency"                  => $countryObj->currency_code, // 币种
            "track_num"                 => $trackingCode, // 追踪号
            "invoice_detail"            => join(',', $invoiceNumber), // 税号
            "platform_remark"           => $data['remarks'], // 买家备注信息
            "order_detail" => $info,
        ];
        return OrderService::getInstance()->addOrder($order);
    }

    /**
     * 获取订单列表
     * @param array $params 请求参数
     * @param bool $replace 订单存在是否替换
     * @example
     * [
     *     "start_date" => strtotime("-5day"), // 开始抓取时间， 默认为今天
     *     "end_date" => time(), // 抓取结束时间，默认为当前时间
     *     "status" => 'ready_to_ship', // 订单状态，默认为 ready_to_ship
     *     "limit" => 100, // 每页加载多少条，默认为 100,
     *     "sort_by" => "updated_at", // 排序方式，默认为 updated_at， 可选值：created_at, updated_at
     * ]
     * @date 2020/08/25
     * @author longli
     */
    public function getOrderList($params = [], $replace = false)
    {
        $account = $this->getAccount();
        // 是否需要刷token
        if(time() - strtotime($account->update_time) > 3600) $this->refreshToken();
        Log::info(sprintf("Lazada 批量同步账号【%d】订单，请求参数: 【%s】", $this->getAccountId(), json_encode($params)));
        $startSyncTime = time();
        $args = [
            'created_after' => $this->formatTimeToDate(!empty($params['start_date']) ? $params['start_date'] : date('Y-m-d'), '+08:00'),
            'created_before' => $this->formatTimeToDate(!empty($params['end_date']) ? $params['end_date'] : '', '+08:00'),
            'status' => !empty($params['status']) ? $params['status'] : 'ready_to_ship',
            'limit' => !empty($params['page_size']) ? $params['page_size'] : 100,
            'sort_by' => !empty($params['sort']) && in_array($params['sort'], ['created_at', 'updated_at']) ? : 'updated_at',
        ];
        foreach($this->apiUrls as $apiUrl)
        {
            $page = 0;
            do
            {
                $args['offset'] = $page * $args['limit'];
                if(!$this->buildClient($apiUrl, '/orders/get', $args,'GET')) break;
                try
                {
                    $response = json_decode($this->client->execute($this->request, $account->token->access_token), true);
                    if($response['code'] != 0)
                    {
                        Log::info(sprintf("Lazada 账号【%d】获取订单异常，响应信息：【%s】，参数：【%s】", $this->getAccount(), $response['message'], json_encode($args)));
                        break;
                    }
                    if(empty($response['data']['orders'])) break; // 无订单数据
                    foreach($response['data']['orders'] as $order)
                    {
                        $order['order_detail'] = $this->getOrderInfo($apiUrl, $order);
                        if(empty($order['order_detail'])) continue;
                        $this->pushOrderToTemp($order['order_id'], $order, $replace);
                    }
                    $page++;
                }catch (Exception $e)
                {
                    Log::info(sprintf("Lazada 账号【%d】获取订单发送请求异常，URL：【%s】，参数：【%s】", $this->getAccount(), $apiUrl, json_encode($args)));
                    break;
                }
            }while($args['limit'] == $response['data']['count']);
        }
        // 添加同步订单日志
        AccountSyncLog::addLog($this->getAccountId(), $startSyncTime, time(), $params);
    }

    /**
     * 获取订单详情
     * @param string $url 站点 URL
     * @param array $order 订单数据
     * @return array 订单详情
     * @date 2020/08/26
     * @author longli
     */
    protected function getOrderInfo($url, $order)
    {
        $this->buildClient($url, "/order/items/get", ["order_id" => $order['order_id']], 'GET');
        try
        {
            $account = $this->getAccount();
            $orderDetail = json_decode($this->client->execute($this->request, $account->token->access_token), true);
            if($orderDetail['code'] != 0)
            {
                Log::info(sprintf("Lazada 账号【%d】获取订单详情服务器异常，订单号【%s】，响应信息：【%s】", $this->getAccountId(), $order['order_id'], $orderDetail['message']));
                return [];
            }
            return $orderDetail['data'];
        }catch (Exception $e)
        {
            Log::info(sprintf("Lazada 账号【%d】获取订单详情请求异常，订单号【%s】", $this->getAccountId(), $order['order_id']));
            return [];
        }
    }

    /**
     * 刷新授权
     * @date 2020/08/25
     * @author longli
     * @return bool
     */
    public function refreshToken()
    {
        $account = $this->getAccount();
        $params = [
            "refresh_token" => $account->token->refresh_token,
        ];
        Log::info(sprintf("Lazada 账号【%d】刷新 token, 参数:【%s】", $this->getAccountId(), json_encode($params)));
        $this->buildClient("https://auth.lazada.com/rest", "/auth/token/refresh", $params);
        try
        {
            $jsonData = json_decode($this->client->execute($this->request), true);
            // 保存 token
            $account->token->access_token = $jsonData["access_token"];
            $account->token->refresh_token = $jsonData["refresh_token"];
            $account->save();
            return true;
        }catch (Exception $e)
        {
            Log::info(sprintf("Lazada 账号【%d】刷新 token 失败, 提示信息:【%s】", $this->getAccountId(), $e->getMessage()));
        }
        return false;
    }

    /**
     * 构建客户端
     * @param string $url 请求 url
     * @param string $uri 请求 uri
     * @param string[] $params 请求参数
     * @param string $method 请求方式，默认为 POST
     * @param string $userAgent 设置请求头
     * @param string $ip 设置请求 ip
     * @date 2020/08/25
     * @return bool
     * @author longli
     */
    public function buildClient($url, $uri, $params = [], $method = 'POST', $userAgent = '', $ip = '')
    {
        $account = $this->getAccount();
        try
        {
            $this->client = new LazopClient($url, $account->token->appkey, $account->token->app_secret, $ip, $userAgent);
            $this->request = new LazopRequest($uri, $method);
            if(!empty($params))
            {
                foreach($params as $k => $v)
                {
                    $this->request->addApiParam($k, $v);
                }
            }
            return true;
        }catch (Exception $e)
        {
            Log::info(sprintf("Lazada 构建客户端异常：【%s】", $e->getMessage()));
        }
        return false;
    }

}